package com.huike.report.service.impl;

import java.math.BigDecimal;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.concurrent.CompletableFuture;
import java.util.stream.Stream;

import com.huike.clues.domain.TbClueTrackRecord;
import com.huike.clues.domain.vo.ClueTrackRecordVo;
import com.huike.common.exception.CustomException;
import com.huike.report.domain.vo.ReportVo;
import com.huike.report.domain.vo.*;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import com.huike.business.mapper.TbBusinessMapper;
import com.huike.clues.domain.TbActivity;
import com.huike.clues.domain.TbAssignRecord;
import com.huike.clues.domain.TbClue;
import com.huike.clues.domain.vo.IndexStatisticsVo;
import com.huike.clues.mapper.SysDeptMapper;
import com.huike.clues.mapper.SysDictDataMapper;
import com.huike.clues.mapper.TbActivityMapper;
import com.huike.clues.mapper.TbAssignRecordMapper;
import com.huike.clues.mapper.TbClueMapper;
import com.huike.common.core.domain.entity.SysDept;
import com.huike.common.utils.SecurityUtils;
import com.huike.contract.domain.TbContract;
import com.huike.contract.mapper.TbContractMapper;
import com.huike.report.mapper.ReportMapper;
import com.huike.report.service.IReportService;

import javax.xml.crypto.Data;

@Service
public class ReportServiceImpl implements IReportService {

    @Autowired
    private TbContractMapper contractMapper;


    @Autowired
    private SysDictDataMapper sysDictDataMapper;


    @Autowired
    private TbClueMapper clueMapper;

    @Autowired
    private TbActivityMapper activityMapper;

    @Autowired
    private TbBusinessMapper businessMapper;

    @Autowired
    private SysDeptMapper deptMapper;

    @Autowired
    private TbAssignRecordMapper assignRecordMapper;

    @Autowired
    private ReportMapper reportMpper;

    @Override
    public LineChartVO contractStatistics(String beginCreateTime, String endCreateTime) {
        LineChartVO lineChartVo =new LineChartVO();
        try {
            List<String> timeList= findDates(beginCreateTime,endCreateTime);
            lineChartVo.setxAxis(timeList);
            List<LineSeriesVO> series = new ArrayList<>();
            List<Map<String,Object>>  statistics = contractMapper.contractStatistics(beginCreateTime,endCreateTime);
            LineSeriesVO lineSeriesDTO1=new LineSeriesVO();
            lineSeriesDTO1.setName("新增客户数");
            LineSeriesVO lineSeriesDTO2=new LineSeriesVO();
            lineSeriesDTO2.setName("客户总数");
            int sum = 0;
            for (String s : timeList) {
                Optional optional=  statistics.stream().filter(d->d.get("dd").equals(s)).findFirst();
                if(optional.isPresent()){
                    Map<String,Object> cuurentData=  (Map<String,Object>)optional.get();
                    lineSeriesDTO1.getData().add(cuurentData.get("num"));
                    sum += Integer.parseInt(cuurentData.get("num").toString());
                }else{
                    lineSeriesDTO1.getData().add(0);
                }
                lineSeriesDTO2.getData().add(sum);
            }
            series.add(lineSeriesDTO1);
            series.add(lineSeriesDTO2);
            lineChartVo.setSeries(series);
        } catch (ParseException e) {
            // e.printStackTrace();
        }
        return  lineChartVo;
    }

    @Override
    public LineChartVO salesStatistics(String beginCreateTime, String endCreateTime) {
        LineChartVO lineChartVo =new LineChartVO();
        try {
            List<String> timeList= findDates(beginCreateTime,endCreateTime);
            lineChartVo.setxAxis(timeList);
            List<LineSeriesVO> series = new ArrayList<>();
            List<Map<String,Object>>  statistics = contractMapper.salesStatistics(beginCreateTime,endCreateTime);
            LineSeriesVO lineSeriesVo=new LineSeriesVO();
            lineSeriesVo.setName("销售统计");
            int sum=0;
            for (String s : timeList) {
                Optional optional=  statistics.stream().filter(d->d.get("dd").equals(s)).findFirst();
                if(optional.isPresent()){
                    Map<String,Object> cuurentData=  (Map<String,Object>)optional.get();
                    lineSeriesVo.getData().add(cuurentData.get("sales"));
                }else{
                    lineSeriesVo.getData().add(0);
                }
            }
            series.add(lineSeriesVo);
            lineChartVo.setSeries(series);
        } catch (ParseException e) {
            // e.printStackTrace();
        }
        return  lineChartVo;
    }




    /**
     * 渠道统计
     */
    @Override
    public List<Map<String, Object>> chanelStatistics(String beginCreateTime, String endCreateTime) {
        List<Map<String, Object>> data= contractMapper.chanelStatistics(beginCreateTime,endCreateTime);
        for (Map<String, Object> datum : data) {
            String subjectValue= (String) datum.get("channel");
            String lable=  sysDictDataMapper.selectDictLabel("clues_item",subjectValue);
            datum.put("channel",lable);
        }
        return data;
    }

    @Override
    public List<TbContract> contractReportList(TbContract tbContract) {
        return contractMapper.selectTbContractList(tbContract);
    }


    @Override
    public List<Map<String, Object>> activityStatistics(String beginCreateTime, String endCreateTime) {
        List<Map<String, Object>> data= contractMapper.activityStatistics(beginCreateTime,endCreateTime);
        for (Map<String, Object> datum : data) {
            Long activityId= (Long) datum.get("activity_id");
            TbActivity tbActivity = activityMapper.selectTbActivityById(activityId);
            if(tbActivity==null){
                datum.put("activity", "其他");
            }else{
                datum.put("activity", tbActivity.getName());
            }
        }
        return data;
    }

    /**
     * 按照部门统计销售
     * @param beginCreateTime
     * @param endCreateTime
     * @return
     */
    @Override
    public List<Map<String, Object>> deptStatisticsList(String beginCreateTime, String endCreateTime) {
        List<Map<String, Object>> data= contractMapper.deptStatistics(beginCreateTime,endCreateTime);
        for (Map<String, Object> datum : data) {
            Long deptId= (Long) datum.get("dept_id");
            if(deptId!=null){
                SysDept dept= deptMapper.selectDeptById(deptId);
                datum.put("deptName", dept.getDeptName());
            }
        }
        return data;
    }


    /**
     * 按照渠道统计销售
     * @param beginCreateTime
     * @param endCreateTime
     * @return
     */
    @Override
    public List<Map<String, Object>> channelStatisticsList(String beginCreateTime, String endCreateTime) {
        List<Map<String, Object>> data= contractMapper.channelStatistics(beginCreateTime,endCreateTime);
        for (Map<String, Object> datum : data) {
            String subjectValue= (String) datum.get("channel");
            if(subjectValue!=null){
                String lable=  sysDictDataMapper.selectDictLabel("clues_item",subjectValue);
                datum.put("channel",lable);
            }
        }
        return data;
    }


    /**
     * 按照归属人统计销售
     * @param beginCreateTime
     * @param endCreateTime
     * @return
     */
    @Override
    public List<Map<String, Object>> ownerShipStatisticsList(String beginCreateTime, String endCreateTime) {
        return  contractMapper.ownerShipStatistics(beginCreateTime,endCreateTime);
    }


    @Override
    public List<TbClue> cluesStatisticsList(TbClue clue) {
        return clueMapper.selectTbClueForReport(clue);
    }

    @Override
    public List<ActivityStatisticsVo> activityStatisticsList(TbActivity query) {
        query.setStatus("2");
        List<TbActivity> activities= activityMapper.selectTbActivityList(query);
        Map<String, Object> timeMap = query.getParams();
        List<ActivityStatisticsVo> list=new ArrayList<>();
        for (TbActivity activity : activities) {
            ActivityStatisticsVo dto = new ActivityStatisticsVo();
            BeanUtils.copyProperties(activity, dto);
            TbClue tbClue = new TbClue();
            tbClue.setActivityId(activity.getId());
            tbClue.setChannel(activity.getChannel());
            tbClue.setParams(timeMap);
            Map<String, Object> clueCount = clueMapper.countByActivity(tbClue);
            if (clueCount != null) {
                dto.setCluesNum(Integer.parseInt(clueCount.get("total").toString()));
                if(clueCount.get("falseClues")!=null){
                    dto.setFalseCluesNum(Integer.parseInt(clueCount.get("falseClues").toString()));
                }
                if (clueCount.get("toBusiness") != null) {
                    dto.setBusinessNum(Integer.parseInt(clueCount.get("toBusiness").toString()));
                }
            }
            TbContract tbContract = new TbContract();
            tbContract.setChannel(activity.getChannel());
            tbContract.setActivityId(activity.getId());
            tbContract.setParams(timeMap);
            Map<String, Object> contractCount = contractMapper.countByActivity(tbContract);
            if (contractCount != null) {
                dto.setCustomersNum(Integer.parseInt(contractCount.get("customersNum").toString()));
                if(contractCount.get("amount")==null) {
                    dto.setAmount(0d);
                }else {
                    dto.setAmount((Double) contractCount.get("amount"));
                }
                if(contractCount.get("cost")==null) {
                    dto.setCost(0d);
                }else {
                    dto.setCost((Double) contractCount.get("cost"));
                }

            }
            list.add(dto);
        }
        return list;
    }

    /**
     * *************看我看我**************
     * 传入两个时间范围，返回这两个时间范围内的所有时间，并保存在一个集合中
     * @param beginTime
     * @param endTime
     * @return
     * @throws ParseException
     */
    public static List<String> findDates(String beginTime, String endTime)
            throws ParseException {
        List<String> allDate = new ArrayList();
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");

        Date dBegin = sdf.parse(beginTime);
        Date dEnd = sdf.parse(endTime);
        allDate.add(sdf.format(dBegin));
        Calendar calBegin = Calendar.getInstance();
        // 使用给定的 Date 设置此 Calendar 的时间
        calBegin.setTime(dBegin);
        Calendar calEnd = Calendar.getInstance();
        // 使用给定的 Date 设置此 Calendar 的时间
        calEnd.setTime(dEnd);
        // 测试此日期是否在指定日期之后
        while (dEnd.after(calBegin.getTime())) {
            // 根据日历的规则，为给定的日历字段添加或减去指定的时间量
            calBegin.add(Calendar.DAY_OF_MONTH, 1);
            allDate.add(sdf.format(calBegin.getTime()));
        }
        System.out.println("时间==" + allDate);
        return allDate;
    }


    @Override
    public IndexVo getIndex(IndexStatisticsVo request) {
        Long deptId= request.getDeptId();
        TbAssignRecord tbAssignRecord=new TbAssignRecord();
        tbAssignRecord.setLatest("1");
        assignRecordMapper.selectAssignRecordList(tbAssignRecord);
        return null;
    }

    @Override
    public List<Map<String, Object>> salesStatisticsForIndex(IndexStatisticsVo request) {
        List<Map<String, Object>> list= contractMapper.contractStatisticsByUser(request);
        for (Map<String, Object> datum : list) {
            Long deptId= (Long) datum.get("dept_id");
            if(deptId!=null){
                SysDept dept= deptMapper.selectDeptById(deptId);
                datum.put("deptName", dept.getDeptName());
            }
        }
        return list;
    }


    /**
     * ************看我看我***********
     * 用我能少走很多路
     * 我是用来机选百分比的方法
      * @param all
     * @param num
     * @return
     */
    private BigDecimal getRadio(Integer all,Long num) {
        if(all.intValue()==0){
            return new BigDecimal(0);
        }
        BigDecimal numBigDecimal = new BigDecimal(num);
        BigDecimal allBigDecimal = new BigDecimal(all);
        BigDecimal divide = numBigDecimal.divide(allBigDecimal,4,BigDecimal.ROUND_HALF_UP);
        return divide.multiply(new BigDecimal(100));
    }


    /**
     * 获取首页基本数据
     * @param beginCreateTime
     * @param endCreateTime
     * @return
     */
    @Override
    public IndexBaseInfoVO getBaseInfo(String beginCreateTime, String endCreateTime) {
        //1）构建一个空的结果集对象
        IndexBaseInfoVO result = new IndexBaseInfoVO();
        //2 封装结果集属性
        // 2.1 由于查询需要用到用户名 调用工具类获取用户名
        String username = SecurityUtils.getUsername();
        try {
            //3 封装结果集对象
            result.setCluesNum(reportMpper.getCluesNum(beginCreateTime, endCreateTime, username));
            result.setBusinessNum(reportMpper.getBusinessNum(beginCreateTime, endCreateTime, username));
            result.setContractNum(reportMpper.getContractNum(beginCreateTime, endCreateTime, username));
            result.setSalesAmount(reportMpper.getSalesAmount(beginCreateTime, endCreateTime, username));
        }catch (Exception e) {
            e.printStackTrace();
            return null;
        }
        //4 返回结果集对象
        return result;
    }

    @Override
    public ReportVo getTodayInfo() {

        Long userId = SecurityUtils.getUserId();
        Long deptId = SecurityUtils.getDeptId();
        String username = SecurityUtils.getUsername();
        String now = new SimpleDateFormat("yyyy-MM-dd").format(new Date());

        int todayCluesNum = reportMpper.getCluesNumByUserIdAndDate(now,userId);
        int todayBusinessNum = reportMpper.getBusinessNumByUserIdAndDate(now,userId);
        int todayContractNum = reportMpper.getContractNumByUserIdAndDate(now,username,deptId);
        Double amount = reportMpper.getTodaySalesAmount(now,username);

        //CompletableFuture<Integer> integerCompletableFuture = CompletableFuture.supplyAsync(() -> {
        //    return reportMpper.getCluesNumByUserIdAndDate(now, userId);
        //});


        ReportVo reportVo = new ReportVo();
        reportVo.setTodayCluesNum(todayCluesNum);
        reportVo.setTodayBusinessNum(todayBusinessNum);
        reportVo.setTodayContractNum(todayContractNum);
        reportVo.setTodaySalesAmount(amount);

        return reportVo;

    }

    @Override
    public Integer getTofollowedCluesNum(String beginCreateTime, String endCreateTime,String username) {
        return reportMpper.getTofollowedCluesNum(beginCreateTime,endCreateTime,username);
    }

    @Override
    public Integer getTofollowedBusinessNum(String beginCreateTime, String endCreateTime,String username) {
        return reportMpper.getTofollowedBusinessNum(beginCreateTime,endCreateTime,username);
    }

    @Override
    public Integer getToallocatedCluesNum(String beginCreateTime, String endCreateTime) {
        return reportMpper.getToallocatedCluesNum(beginCreateTime,endCreateTime);
    }

    @Override
    public Integer getToallocatedBusinessNum(String beginCreateTime, String endCreateTime,String username) {
        return reportMpper.getToallocatedBusinessNum(beginCreateTime,endCreateTime,username);
    }

    @Override
    public List<MySubjectStatisticsVo> subjectStatisticsList(String beginCreateTime, String endCreateTime) {
        return reportMpper.getSubjectStatisticsList(beginCreateTime,endCreateTime);
    }

    //@Override
    //public MyClueStatisticsVo cluesStatisticsList(String beginCreateTime, String endCreateTime) {
    //    MyClueStatisticsVo clueStatistics = new MyClueStatisticsVo();
    //    List<String> xAxisList = new LinkedList<>();
    //    SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd");
    //    try {
    //        //把字符串转换成Date对象
    //        Date begin = simpleDateFormat.parse(beginCreateTime);
    //        Date end = simpleDateFormat.parse(endCreateTime);
    //        //把第一天加进去
    //        xAxisList.add(beginCreateTime);
    //        //date对象转换成calender对象
    //        Calendar instance = Calendar.getInstance();
    //        instance.setTime(begin);
    //        //把从begin到end的所有日期假如xAxisList内，最后赋给VO对象的xAxis属性
    //        while (begin.getTime() < end.getTime()) {
    //
    //            instance.add(Calendar.DAY_OF_MONTH,1);
    //            Date time = instance.getTime();
    //            String format = simpleDateFormat.format(time);
    //            xAxisList.add(format);
    //            //步进表达式
    //            begin=time;
    //        }
    //
    //    } catch (ParseException e) {
    //        e.printStackTrace();
    //    }
    //    clueStatistics.setxAxis(xAxisList);
    //    //series
    //    List<MyClueNumVo> myClueNumVos = new LinkedList<>();
    //    //新增线索数量
    //    MyClueNumVo addClueNum = new MyClueNumVo();
    //    addClueNum.setName("新增线索数量");
    //    List<Integer> addNumList = new LinkedList<>();
    //    //线索总数量
    //    MyClueNumVo sumClueNum = new MyClueNumVo();
    //    sumClueNum.setName("线索总数量");
    //    List<Integer> sumNumList = new LinkedList<>();
    //    //从库中查询在参数范围内的每天的线索数
    //    List<MyClueNumDto> query = reportMpper.getAddClueSeries(beginCreateTime,endCreateTime);
    //
    //    int sum=0;
    //    lo:for (int i = 0; i < xAxisList.size(); i++) {
    //        String time = xAxisList.get(i);
    //        //看看库里面的数据是否有当前time
    //        for (MyClueNumDto myClueNumDto : query) {
    //            //有就结束循环
    //            if (myClueNumDto.getFormatCreateTime().equals(time)) {
    //                addNumList.add(myClueNumDto.getClueNum());
    //                sum+=myClueNumDto.getClueNum();
    //                sumNumList.add(sum);
    //                continue lo;
    //            }
    //        }
    //        sumNumList.add(sum);
    //        addNumList.add(0);
    //    }
    //    addClueNum.setData(addNumList);
    //    sumClueNum.setData(sumNumList);
    //    myClueNumVos.add(addClueNum);
    //    myClueNumVos.add(sumClueNum);
    //    //reportMpper.getSumClueSeries();
    //    clueStatistics.setSeries(myClueNumVos);
    //    return clueStatistics;
    //}


    @Override
    public LineChartVO cluesStatisticsList(String beginCreateTime, String endCreateTime) {
        //不在这里判空，在sql语句中判空

        //创建线索数据对象
        LineChartVO cluesStatistic = new LineChartVO();
        //LineChartVO对象把名为xAixs的集合给初始化好，我们可以直接get到往里面添加数据，不用再创建然后再塞回LineChartVO对象中
        List<String> xAxis = cluesStatistic.getxAxis();
        List<LineSeriesVO> series = cluesStatistic.getSeries();

        //往xAxis中添加统计的日期
        //利用Calender对象实现这个功能
        Calendar instance4change = Calendar.getInstance();
        Calendar endInstance = Calendar.getInstance();
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
        Date beginDate = null;
        Date endDate = null;
        try {
            beginDate = sdf.parse(beginCreateTime);
            endDate = sdf.parse(endCreateTime);
            instance4change.setTime(beginDate);
            endInstance.setTime(endDate);
        } catch (ParseException e) {
            //todo 抛出解析异常如何解决
        }
        //先把第一天添加进list集合中
        xAxis.add(beginCreateTime);
        //再把其余的通过循环添加进去，由于不知道要添加的次数，选择while循环
        //循环条件
        while (endInstance.after(instance4change)) {
            //日期加一天，并添加到xAxis中
            instance4change.add(Calendar.DAY_OF_MONTH,1);//步进表达式
            xAxis.add(sdf.format(instance4change.getTime()));
        }

        //往series中添加新增线索数量对象和线索总数量对象
        LineSeriesVO addClue = new LineSeriesVO();
        LineSeriesVO sumClue = new LineSeriesVO();
        addClue.setName("新增线索数量");
        sumClue.setName("线索总数量");
        //往data里面添加每天新增线索数量数据
        //查询数据库每天新增数量
        List<Map<String,Object>> queryClueStatistics = reportMpper.cluesStatistics(beginCreateTime, endCreateTime);
        //每一行数据相当于一个对象，可以用Map集合表示，键是字段，值就是字段值，多行数据存储到list集合中
        //for (Map<String, Integer> queryClueStatistic : queryClueStatistics) {
        //    for (Map.Entry<String, Integer> entry : queryClueStatistic.entrySet()) {
        //        System.out.print(entry.getKey()+"::::::"+entry.getValue()+",");
        //    }
        //    System.out.println();
        //}
        //System.out.println(queryClueStatistics);

        //下面开始补0，同时求每日线索总数
        int sum = 0;
        for (String s : xAxis) {
            //从查询结果中筛选出当前日期s有没有新增线索
            Stream<Map<String, Object>> dd = queryClueStatistics.stream().filter(map -> map.get("dd").equals(s));
            //findFirst() : 返回流中的第一个元素；如果流是空的，则返回空；
            Optional<Map<String, Object>> first = dd.findFirst();
            if (first.isPresent()) {
                //当前日期s有新增线索
                Map<String, Object> map = first.get();
                addClue.getData().add(map.get("num"));
                sum += (Long) map.get("num");//求出累计线索数
            } else {
                //当前日期s没有新增线索
                addClue.getData().add(0);
            }
            sumClue.getData().add(sum);
        }
        System.out.println("data:"+addClue.getData());
        cluesStatistic.getSeries().add(addClue);
        cluesStatistic.getSeries().add(sumClue);

        //将数据返回给controller层
        return cluesStatistic;
    }

    @Override
    public List<ClueTrackRecordVo> getClueTrackRecordByClueId(Long clueId) {
        return reportMpper.getClueTrackRecordByClueId(clueId);
    }

    @Override
    public void updateClueTrackRecord(ClueTrackRecordVo tbClueTrackRecord) {
        reportMpper.updateClueTrackRecord(tbClueTrackRecord);
        TbClueTrackRecord newClueTrackRecord = new TbClueTrackRecord();
        BeanUtils.copyProperties(tbClueTrackRecord,newClueTrackRecord);
        newClueTrackRecord.setCreateBy(SecurityUtils.getUsername());
        newClueTrackRecord.setCreateTime(new Date());
        int id = reportMpper.addClueTrackRecord(newClueTrackRecord);
        if (id<=0) {
            throw new CustomException("新增线索跟进记录失败！！！");
        }
        System.out.println("新增线索跟进记录成功，新增的线索记录id为："+id);
    }
}